package com.mspbots.attendance.trigger;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.mspbots.api.client.CoreClient;
import com.mspbots.attendance.mapper.TenantAttendanceMapper;
import com.mspbots.attendance.model.TenantAttendance;
import com.mspbots.attendance.model.TenantUserMapping;
import com.mspbots.attendance.request.SheetsTimeDTO;
import com.mspbots.attendance.service.impl.TenantAttendanceServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import java.time.Duration;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;


/**
 * com.mspbots.tsheet.trigger.TsheetTriggerEvent
 *
 * @author Jason
 * @date 2019/12/19
 **/

@Slf4j
@Component
public class TsheetTriggerEvent {

    @Autowired
    private TenantAttendanceMapper tenantAttendanceMapper;

    @Autowired
    private TenantAttendanceServiceImpl tenantAttendanceServiceImpl;

    @Autowired
    private ObjectMapper objectMapper;

    @Autowired
    private CoreClient coreClient;

    //    @RabbitListener(queues = "attendance.sheet.TsheetInCheck")
    public void publishTicketTriggerEvent(SheetsTimeDTO tsheetsTimeDTO) {
        log.info("tsheet records [{}]", objectMapper.convertValue(tsheetsTimeDTO, JsonNode.class));
        if (tsheetsTimeDTO.getLastModified() != null && LocalDateTime.now().minusHours(24).isBefore(tsheetsTimeDTO.getLastModified())) {

            if (!ObjectUtils.isEmpty(tsheetsTimeDTO.getEndTime())) {
                log.info("sheet EndTime is not null{}", tsheetsTimeDTO.getSheetUserId());
                return;
            }
            Map<String, Object> userMappingParam = Map.of(
                    "tenantId", tsheetsTimeDTO.getTenantId(),
                    "sheetUserId", tsheetsTimeDTO.getSheetUserId()
            );
            TenantUserMapping userMapping = tenantAttendanceMapper.selectUserMappingBySheetUserId(userMappingParam);
            if (!ObjectUtils.isEmpty(userMapping)) {
                log.info("user info : {}", userMapping.getId());
                TenantAttendance tenantAttendance = new TenantAttendance();
                tenantAttendance.setTenantId(tsheetsTimeDTO.getTenantId());
                tenantAttendance.setTeamsUserId(userMapping.getTeamsUserId());
                tenantAttendance.setLogTime(ObjectUtils.isEmpty(tsheetsTimeDTO.getEndTime()) ? tsheetsTimeDTO.getStartTime() : tsheetsTimeDTO.getEndTime());
                //tenantAttendance.setDuration(tsheetsTimeDTO.getDuration()/60);
                tenantAttendance.setFromType("Tsheet");
                tenantAttendance.setUserId(userMapping.getUserId());
                tenantAttendance.setCreateTime(LocalDateTime.now());
                if (!ObjectUtils.isEmpty(userMapping.getTenantUserId())) {
                    TenantAttendance timezoneObj = tenantAttendanceMapper.selectUserTimezone(userMapping.getTenantUserId());
                    if (!ObjectUtils.isEmpty(timezoneObj)) {
                        tenantAttendance.setTimezone(timezoneObj.getTimezone());
                        tenantAttendance.setTimezoneOffset(timezoneObj.getTimezoneOffset());
                    } else {
                        if (!ObjectUtils.isEmpty(userMapping.getTenantId())) {
                            TenantAttendance tzObj = tenantAttendanceMapper.selectTenantTimezone(userMapping.getTenantId());
                            if (!ObjectUtils.isEmpty(tzObj)) {
                                tenantAttendance.setTimezone(tzObj.getTimezone());
                                tenantAttendance.setTimezoneOffset(tzObj.getTimezoneOffset());
                            } else {
                                tenantAttendance.setTimezone("UTC");
                                tenantAttendance.setTimezoneOffset("+00:00");
                            }
                        }
                    }
                } else {
                    if (!ObjectUtils.isEmpty(userMapping.getTenantId())) {
                        TenantAttendance tzObj = tenantAttendanceMapper.selectTenantTimezone(userMapping.getTenantId());
                        if (!ObjectUtils.isEmpty(tzObj)) {
                            tenantAttendance.setTimezone(tzObj.getTimezone());
                            tenantAttendance.setTimezoneOffset(tzObj.getTimezoneOffset());
                        } else {
                            tenantAttendance.setTimezone("UTC");
                            tenantAttendance.setTimezoneOffset("+00:00");
                        }
                    } else {
                        tenantAttendance.setTimezone("UTC");
                        tenantAttendance.setTimezoneOffset("+00:00");
                    }
                }


                tenantAttendance.setAction("in");
                tenantAttendance.setPaid(true);
                List<String> teamNames = this.tenantAttendanceMapper.selectTenantUserExtend(tenantAttendance);
                Set<String> set = this.tenantAttendanceServiceImpl.dealWithTeam(teamNames);
                String teamStr = String.valueOf(new ArrayList<String>(set));
                if (ObjectUtils.isEmpty(teamStr) || teamStr.equals("[]")) {
                    tenantAttendance.setTeam("Ungrouped");
                } else {
                    tenantAttendance.setTeam(teamStr);
                }
                tenantAttendance.setUsername(userMapping.getUserName());
                tenantAttendance.setReason(tsheetsTimeDTO.getNotes());
                List<TenantAttendance> userLogs = tenantAttendanceMapper.selectCurrentDayLog(tenantAttendance);
                log.info("tsheet record  userLogs {}", CollectionUtils.isEmpty(userLogs) ? 0 : userLogs.size());

                if (!CollectionUtils.isEmpty(userLogs)) {
                    TenantAttendance attendanceLog = userLogs.get(0);
                    String action = attendanceLog.getAction();
                    String subAction = attendanceLog.getSubAction();
                    if (action.toLowerCase().equals("in")) {
                        if (!ObjectUtils.isEmpty(subAction)) {
                            attendanceLog(attendanceLog);
                            tenantAttendance.setAction("out");
                            tenantAttendance.setSubAction(null);
                            tenantAttendance.setLogTime(tenantAttendance.getLogTime().minusSeconds(1));
                            tenantAttendanceMapper.insert(tenantAttendance);
                            tenantAttendance.setAction("in");
                            tenantAttendance.setLogTime(tenantAttendance.getLogTime().plusSeconds(1));
                            tenantAttendanceMapper.insert(tenantAttendance);
                            log.info("last log record is IN back {},1 out 2 IN", tsheetsTimeDTO.getSheetUserId());
                        } else {
                            log.info("last log record is IN NULL,do nothing {}", tsheetsTimeDTO.getSheetUserId());
                        }
                    }
                    if (action.toLowerCase().equals("out")) {
                        Boolean flag = true;
                        if (!ObjectUtils.isEmpty(subAction)) {
                            flag = false;
                            log.info("last log record is OUT BREAK/LUNCH {},1 BACK 2 OUT", tsheetsTimeDTO.getSheetUserId());
                            tenantAttendance.setAction("in");
                            tenantAttendance.setSubAction("back");
                            tenantAttendance.setLogTime(tenantAttendance.getLogTime().minusSeconds(2));
                            tenantAttendanceMapper.insert(tenantAttendance);
                            tenantAttendance.setAction("out");
                            tenantAttendance.setSubAction(null);
                            tenantAttendance.setLogTime(tenantAttendance.getLogTime().plusSeconds(1));
                            tenantAttendanceMapper.insert(tenantAttendance);
                        }
                        log.info("last log record is OUT BREAK/LUNCH/NULL,3 IN", tsheetsTimeDTO.getSheetUserId());
                        tenantAttendance.setAction("in");
                        tenantAttendance.setSubAction(null);
                        if (!flag) {
                            tenantAttendance.setLogTime(tenantAttendance.getLogTime().plusSeconds(1));
                        }
                        tenantAttendanceMapper.insert(tenantAttendance);
                        attendanceLog(attendanceLog);
                    }
                } else {
                    tenantAttendanceMapper.insert(tenantAttendance);
                }
                log.info("tsheet record {}", tenantAttendance.getLogTime());
            } else {
                log.info("tsheet user [{}] has no mapping [{}]", tsheetsTimeDTO, tsheetsTimeDTO.getSheetId());
            }

        } else {
            log.info("sheet lastupdated time is 24 hours before not null{}", tsheetsTimeDTO.getSheetUserId());
        }

    }

    private void attendanceLog(TenantAttendance attendanceLog) {
        attendanceLog.setDuration(Duration.between(attendanceLog.getLogTime(), LocalDateTime.now()).toMinutes());
        tenantAttendanceServiceImpl.saveOrUpdate(attendanceLog);
    }

}
